﻿using SD.Infrastructure.Repository.EntityFrameworkCore;
using SD.Infrastructure.RepositoryBase;
using SlamDunk.MES.Domain.Entities.FoundationContext;
using SlamDunk.MES.Domain.IRepositories.Interfaces.FoundationContext;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace SlamDunk.MES.Repository.Implements.FoundationContext
{
    /// <summary>
    /// 计量单位仓储实现
    /// </summary>
    public class MeasureUnitRepository : EFEntityRepositoryProvider<MeasureUnit>, IMeasureUnitRepository
    {
        #region # 分页获取计量单位列表 —— ICollection<MeasureUnit> FindByPage(string keywords...
        /// <summary>
        /// 分页获取计量单位列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="unitGroupId">计量单位组Id</param>
        /// <param name="isMaster">是否主计量单位</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="rowCount">总记录数</param>
        /// <param name="pageCount">总页数</param>
        /// <returns>计量单位列表</returns>
        public ICollection<MeasureUnit> FindByPage(string keywords, Guid? unitGroupId, bool? isMaster, int pageIndex, int pageSize, out int rowCount, out int pageCount)
        {
            Expression<Func<MeasureUnit, bool>> condition =
                x =>
                    (string.IsNullOrEmpty(keywords) || x.Number.Contains(keywords) || x.Name.Contains(keywords) ||
                     x.Description.Contains(keywords)) &&
                    (unitGroupId == null || x.MeasureUnitGroup.Id == unitGroupId) &&
                    (isMaster == null || x.IsMaster == isMaster);

            IOrderedQueryable<MeasureUnit> measureUnits = base.Find(condition).OrderBy(x => x.MeasureUnitGroup.Id).ThenBy(x => x.Sort);
            IQueryable<MeasureUnit> result = measureUnits.ToPage(pageIndex, pageSize, out rowCount, out pageCount);

            return result.ToList();
        }
        #endregion

        #region # 获取计量单位列表 —— ICollection<MeasureUnit> FindByGroup(Guid groupId)
        /// <summary>
        /// 获取计量单位列表
        /// </summary>
        /// <param name="groupId">计量单位组Id</param>
        /// <returns>计量单位列表</returns>
        public ICollection<MeasureUnit> FindByGroup(Guid groupId)
        {
            IQueryable<MeasureUnit> measureUnits = base.Find(x => x.MeasureUnitGroup.Id == groupId);

            return measureUnits.ToList();
        }
        #endregion

        #region # 获取计量单位字典 —— IDictionary<string, MeasureUnit> Find(IEnumerable<string>...
        /// <summary>
        /// 获取计量单位字典
        /// </summary>
        /// <param name="unitNos">计量单位编号集</param>
        /// <returns>计量单位字典</returns>
        public IDictionary<string, MeasureUnit> Find(IEnumerable<string> unitNos)
        {
            #region # 验证

            string[] unitNos_ = unitNos?.Distinct().ToArray() ?? new string[0];
            if (!unitNos_.Any())
            {
                return new Dictionary<string, MeasureUnit>();
            }

            #endregion

            var entities = from entity in base.FindAllInner()
                           where unitNos_.Contains(entity.Number)
                           select new { entity.Number, entity };

            return entities.ToDictionary(x => x.Number, x => x.entity);
        }
        #endregion

        #region # 是否存在计量单位 —— bool Exist(Guid? measureUnitId, string measureUnitNo)
        /// <summary>
        /// 是否存在计量单位
        /// </summary>
        /// <param name="measureUnitId">计量单位Id</param>
        /// <param name="measureUnitNo">计量单位编号</param>
        /// <returns>是否存在</returns>
        public bool Exist(Guid? measureUnitId, string measureUnitNo)
        {
            if (measureUnitId != null)
            {
                MeasureUnit measureUnit = this.SingleOrDefault(measureUnitId.Value);
                if (measureUnit != null && measureUnit.Number == measureUnitNo)
                {
                    return false;
                }

                return base.Exists(x => x.Number == measureUnitNo);
            }

            return base.Exists(x => x.Number == measureUnitNo);
        }
        #endregion
    }
}
